package org.red5.audio;

import java.io.File;
import java.io.FileNotFoundException;
import java.sql.Timestamp;

import org.red5.core.Application;
import org.red5.core.ApplicationSettings;
import org.red5.logging.Red5LoggerFactory;
import org.red5.server.api.IConnection;
import org.red5.server.stream.ClientBroadcastStream;
import org.slf4j.Logger;

import com.meevle.business.SetDelegate;
import com.meevle.business.SlotDelegate;
import com.meevle.dao.SetDAO;
import com.meevle.dao.SlotDAO;
import com.meevle.dao.UserDAO;
import com.meevle.utilities.DaoToVoAdapter;
import com.meevle.utilities.RegexController;
import com.meevle.vo.SetVO;
import com.meevle.vo.SlotVO;
import com.meevle.vo.UserVO;

/**
 * <code>StreamManager</code> provides services for recording the broadcast
 * stream.
 */
public class Recorder {

	// Application components
	private Application app;
	private static Logger log = Red5LoggerFactory.getLogger(Recorder.class, "Meevle");
	public Recorder()
	{}
	
	/**
	 * Start recording the publishing stream for the specified
	 * <code>IConnection</code>.
	 * 
	 * @param conn The specified <code>IConnection</code>
	 * @param userVo The user that's recording
	 * @throws Exception When something went wrong during the saving of the stream to the server
	 */
	public void startRecord(IConnection conn, String userName, String setName, int slotIndex) throws Exception
	{
		try {
			RegexController.getInstance().checkUsername(userName);
		} catch (Exception e) {
			throw e;
		}
		
		SetVO setVo = new SetVO();
		UserVO u = new UserVO();
		u.setUsername(userName);
		setVo.setName(setName);
		setVo.setOwner(u);
		
		SetDAO set = SetDAO.getSet(setVo);
		for(SlotDAO slot : set.getSlots())
		{
			if(slot.getSlotIndex() == slotIndex)
			{
				SetDelegate.removeSlotFromSet(DaoToVoAdapter.getInstance().getSlotFromSlotDAO(slot), setVo);
				
			}
		}
		
		// Get a reference to the current broadcast stream.
		log.info("Start Recording");
		ClientBroadcastStream stream = (ClientBroadcastStream) app
				.getBroadcastStream(conn.getScope(), userName);

		stream.setClientBufferDuration(2000);
		
		String streamTemp =
				ApplicationSettings.getInstance().getUserSetPathWithoutStreams(userName, setName)
				+ File.separator
				+ ApplicationSettings.getInstance().getTempStreamName();
		try {
			// Save the stream to disk.
			System.out.println("\nwordt opgeslaan onder: " + streamTemp);
			stream.saveAs(streamTemp, false);
		} catch (Exception e) {
			log.error("Error saving stream: " + userName +"\n");
			e.printStackTrace();
			throw new Exception("Something went wrong during the saving of your song to the server.");
		}
	}

	/**
	 * Stops recording the publishing stream for the specified
	 * <code>IConnection</code>. Converts the .flv to an .mp3, deletes the original .flv and persists
	 * the new slot into the DB
	 *  
	 * @param conn The <code>IConnection</code> 
	 * @param username The username of the user that's stopping the recording
	 * @return A <code>TrackVO</code> object that contains nothing more than the track name
	 * @throws IllegalArgumentException if something was wrong with the parameters. The Exceptionmessage should tell more.
	 * @throws Exception if something else went wrong like for example the right directory was not found.
	 */
	public SlotVO stopRecord(IConnection conn, String username, String setName, int slotIndex, String slotName) throws IllegalArgumentException, Exception
	{
		try {
			RegexController.getInstance().checkUsername(username);
			UserDAO.getUser(new UserVO(username));
		} catch (Exception e) {
			throw e;
		}
		
		//Get a reference to the current broadcast stream.
		ClientBroadcastStream stream = (ClientBroadcastStream) app.getBroadcastStream(conn.getScope(), username);
		String streamRelativePath = stream.getSaveFilename();
		
		// Stop recording.
		stream.stopRecording();
		
		
		//convert .flv to .mp3
		String sourceFile =
				ApplicationSettings.getInstance().getContextFullPath()
				+ streamRelativePath;
		String destinationDirectory =
				ApplicationSettings.getInstance().getContextFullPath()
//				+ ApplicationSettings.getInstance().getUserTempPath(username)
				+ ApplicationSettings.getInstance().getUserSetPath(username, setName)
				+ File.separator;
		
//		String newFileName = ApplicationSettings.getInstance().getTempStreamName() + ".mp3";
		String newFileName = String.valueOf( System.currentTimeMillis() ) + ".mp3";

		System.out.println("\nSourceFile: " + sourceFile);
		System.out.println("\nDesinationdir: " + destinationDirectory);
		
		try {
			//CONVERTEREN!
			convert(sourceFile, destinationDirectory, newFileName);
		} catch (FileNotFoundException e) {
			log.error("Couldn't find a certain file: \n" + e.getMessage());
			e.printStackTrace();
			throw new Exception("The right directory was not found");
		} catch (RuntimeException e) {
			log.error("RuntimeException somehow\n" + e.getMessage());
			e.printStackTrace();
			throw new Exception("Runtime Exception during converting");
		}
		
		SetVO setVo = new SetVO();
		UserVO u = new UserVO();
		u.setUsername(username);
		setVo.setName(setName);
		setVo.setOwner(u);
		
		
		SlotVO trackVo = new SlotVO();
		trackVo.setName(slotName);
		trackVo.setOwner(DaoToVoAdapter.getInstance().getUserFromUserDAO(UserDAO.getUser(new UserVO(username) ) ) );
		trackVo.setTimeCreated(new Timestamp(System.currentTimeMillis() ) );
		trackVo.setFilename(newFileName.replace('\\', '/'));
		trackVo.setDirectory(ApplicationSettings.getInstance().getUserSetPath(username, setName).replace('\\', '/'));
		trackVo.setIndex(slotIndex);
		
	 
		
//		persisting the new slot to the DB
//		added since 13/04/2009
		try {
            if (SlotDelegate.persistSlot(trackVo))
                UserDAO.addSlotToUser(trackVo.getOwner(), trackVo);
            else
            	System.out.println("\nSlotDelegate: createSlot : Persisten van track naar DB is niet gelukt");
    } catch (Exception e) {
            e.printStackTrace();
    }
    
    SetDelegate.addSlot(setVo, trackVo);
    
	
		return trackVo;
	}

	/*
	 * If recording has stopped, convert stream from flv to mp3 and store in
	 * user streams folder
	 */
	private void convert(String sourceFile, String destinationDirectory, String newFileName) throws FileNotFoundException, RuntimeException {
		AudioConverter flvToMp3Converter = 
			new FlvToMp3AudioConverter(	sourceFile, destinationDirectory, newFileName);
		flvToMp3Converter.setDeleteSource(true);
		flvToMp3Converter.convert();
	}

	/* ----- Spring injected dependencies ----- */

	public void setApplication(Application application) {
		this.app = application;
	}
}
